/************************************************************************************** 
    WFProcess

    Copyright (C) 2010 =OsDevD=

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 **************************************************************************************
 */
package ez.workflow.process;

import java.security.Principal;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import ez.workflow.activity.WFActivityI;
import ez.workflow.event.WFEvent;
import ez.workflow.exceptions.WFException;
import ez.workflow.exceptions.WFProcessException;
import ez.workflow.process.template.WFTemplate;
import ez.workflow.transition.WFTransitionLink;

/**
 * 
 * Run time definition of the workflow.
 * 
 * @author OsDevD
 * 
 */
public class WFProcess extends WFTemplate {

	private Map processAttrMap;

	private WFActivityI processFirstWFActivity;

	private boolean processStarted;

	/** workflow task execution history */
	public final LinkedList processTaskHistory;

	/** workflow process id */
	private int processId;

	/** workflow owner */
	private final Principal processOwner;

	private String processState;

	private WFActivityI processCurrentWFActivity;

	private WFProcessManager processManager;

	public WFProcess(WFTemplate template, String message, Principal owner) {
		processAttrMap = null;
		processCurrentWFActivity = null;
		processTaskHistory = new LinkedList();
		processId = 10; // need to generate wf id

		processManager = null;

		processOwner = owner;

		processState = WFProcessStates.CREATED;

	}

	public Map getProcessAttrMap() {
		return processAttrMap;
	}

	public void setProcessAttrMap(Map processAttrMap) {
		this.processAttrMap = processAttrMap;
	}

	public WFActivityI getFirstWFActivity() {
		return processFirstWFActivity;
	}

	public void setFirstWFActivity(WFActivityI firstWFActivity) {
		this.processFirstWFActivity = firstWFActivity;
	}

	public boolean isWfStarted() {
		return processStarted;
	}

	public void setWfStarted(boolean wfStarted) {
		this.processStarted = wfStarted;
	}

	public int getWfid() {
		return processId;
	}

	public void setWfid(int wfid) {
		this.processId = wfid;
	}

	public WFActivityI getCurrentWFActivity() {
		return processCurrentWFActivity;
	}

	public void setCurrentWFActivity(WFActivityI currentWFActivity) {
		this.processCurrentWFActivity = currentWFActivity;
	}

	public WFProcessManager getProcessManager() {
		return processManager;
	}

	public void setProcessManager(WFProcessManager processManager) {
		this.processManager = processManager;
	}

	public LinkedList getProcessTaskHistory() {
		return processTaskHistory;
	}

	public Principal getWfOwner() {
		return processOwner;
	}

	/**
	 * main activity execution method
	 */
	public void executeCurrentWFAcitivty() {

		WFTransitionLink result = null;

		while (processCurrentWFActivity != null) {

			// Start and execute the current Activity
			if (!processCurrentWFActivity.isStarted()) {
				processCurrentWFActivity.start();
			}
			try {
				// 
				result = processCurrentWFActivity.execute();

				if (!processCurrentWFActivity.isCompleted()) {
					// currentWFActivity.setOutcomingWFTransitionLink(result);
				}
			} catch (Exception e) {
				e.printStackTrace();
			}

			WFActivityI nextWFActivity = processCurrentWFActivity
					.getSuccessorWFActivity(result);
			if (nextWFActivity == null) {
				processComplete(); // process complete
				break;
			}

			// Add the next step to WFEngine history, and mark as current
			processTaskHistory.add(nextWFActivity);

			processCurrentWFActivity = nextWFActivity;
		}
	}

	public void processComplete() {

	}

	public synchronized void processStart() {

		if (this.processState == WFProcessStates.TERMINATED) {
			throw new IllegalStateException(
					WFProcessException.exceptionTerminated);
		}
		if (this.processStarted) {
			throw new IllegalStateException(WFProcessException.exceptionStarted);
		}
		this.processStarted = true;
		this.processState = WFProcessStates.RUNNING;

		processPerformEvent(WFEvent.RUNNING);

		// Mark the first step as the current one & add to history
		this.processCurrentWFActivity = processFirstWFActivity;
		this.processTaskHistory.add(processCurrentWFActivity);

		
		try {
			executeCurrentWFAcitivty();
		} catch (Exception e) {
			processAbort(e);
			
		}
	}

	public void processPerformEvent(String type) {

	}

	public void processAbort(Exception e) {
	
	}

}
